#include "stdafx.h"
#include <stdio.h>
#include "SerialPort.h"

//////////////////////////////////////////////////////////////////////////

enum { TEXT_BUFFER_SIZE = 128, };

//////////////////////////////////////////////////////////////////////////

CSerialPort::CSerialPort()
{
 	m_bSet = false ;
	m_hComm= NULL  ;
}

CSerialPort::~CSerialPort()
{
}

void WriteTrace(char* str)
{
// 	FILE *fp= fopen("c:\\comErr.txt","at");
// 	fputs(str,fp);
// 	fputs("\n",fp);
// 	fclose(fp);
}

bool CSerialPort::Set(DWORD  nBaudRate,BYTE nByteSize,BYTE nParity,BYTE nStopBits)
{
    DCB dcb;
    dcb.DCBlength = sizeof( DCB );
	GetCommState( m_hComm, &dcb );
//    if( !GetCommState( m_hComm, &dcb ))
//	{
//		WriteTrace("GetCommState fail at set");
//		return false ;
//	}
    dcb.BaudRate = nBaudRate;
    dcb.ByteSize = nByteSize;
	dcb.Parity   = nParity;
	dcb.StopBits = nStopBits;
	SetCommState( m_hComm, &dcb );
//    if( SetCommState( m_hComm, &dcb ))
//	{
//		return true;
//	}
//	else
//	{
//		WriteTrace("SetCommState fail at set");
//		return false;
//	}
	PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
	return true ;
}
bool CSerialPort::Open(UINT nCom,DWORD  nBaudRate,BYTE nByteSize,BYTE nParity,BYTE nStopBits)
{
	if( IsOpen() )
	{
		Close();
	}
	char szPort[15]={0};
  	sprintf( szPort, "\\\\.\\COM%d", nCom+1);
	m_hComm = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
	if( m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE )
	{
		m_hComm = NULL ;	
		WriteTrace("Create File fail");
		return false;
	}
	memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
	memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
	
	COMMTIMEOUTS CommTimeOuts;
	CommTimeOuts.ReadIntervalTimeout = 50;
	CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
	CommTimeOuts.ReadTotalTimeoutConstant = 0;
	CommTimeOuts.WriteTotalTimeoutMultiplier = 50;
	CommTimeOuts.WriteTotalTimeoutConstant = 5000;
	if(!SetCommTimeouts( m_hComm, &CommTimeOuts ))
	{
		WriteTrace("SetCommTimeouts fail");
        CloseHandle( m_hComm );
		m_hComm = NULL; 
		return false;
	}
	
	m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
    if( m_OverlappedRead.hEvent == NULL )
	{
		WriteTrace("CreateEvent m_OverlappedRead.hEven fail");
        CloseHandle( m_hComm );
		m_hComm = NULL; 
		return false;
	}

	m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
    if( m_OverlappedWrite.hEvent == NULL )
	{
		WriteTrace("CreateEvent m_OverlappedWrite.hEven fail");
        CloseHandle( m_OverlappedRead.hEvent );
		m_OverlappedRead.hEvent = NULL;
        CloseHandle( m_hComm );
		m_hComm = NULL; 
		return false;
	}
	DCB dcb;
    dcb.DCBlength = sizeof( DCB );
//	GetCommState( m_hComm, &dcb );
    if(!GetCommState( m_hComm, &dcb ))
	{
		WriteTrace("GetCommState fail");
        CloseHandle( m_OverlappedRead.hEvent );
		m_OverlappedRead.hEvent = NULL;
        CloseHandle( m_OverlappedWrite.hEvent );
		m_OverlappedWrite.hEvent = NULL;
        CloseHandle( m_hComm );
		m_hComm = NULL; 
		return false;
	}

    dcb.BaudRate = nBaudRate;
    dcb.ByteSize = nByteSize;
	dcb.Parity   = nParity;
	dcb.StopBits = nStopBits;
//	SetCommState( m_hComm, &dcb );
    if( !SetCommState( m_hComm, &dcb ))
	{
		char buf[1024];
		sprintf(buf,"SetCommState fail -----Com%d",nCom);
		WriteTrace(buf);
        CloseHandle( m_OverlappedRead.hEvent );
		m_OverlappedRead.hEvent = NULL;
        CloseHandle( m_OverlappedWrite.hEvent );
		m_OverlappedWrite.hEvent = NULL;
        CloseHandle( m_hComm );
		m_hComm = NULL; 
		return false;
	}
//	SetupComm( m_hComm, 1024, 1024 );
    if(!SetupComm( m_hComm, 512, 512 ))
    {
		WriteTrace("SetupComm fail");
        CloseHandle( m_OverlappedRead.hEvent );
		m_OverlappedRead.hEvent = NULL;
        CloseHandle( m_OverlappedWrite.hEvent );
		m_OverlappedWrite.hEvent = NULL;
        CloseHandle( m_hComm );
		m_hComm = NULL; 
		return false;
    }
	PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
    return true;
}

VOID CSerialPort::Close()
{
	if(IsOpen())
	{
		CloseHandle(m_hComm);	m_hComm = NULL;
		CloseHandle( m_OverlappedRead.hEvent );
        CloseHandle( m_OverlappedWrite.hEvent );
		m_OverlappedRead.hEvent = NULL;
		m_OverlappedWrite.hEvent = NULL;
	}
}

bool CSerialPort::IsOpen()
{ 
    if( m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE )
		return false ;
	else
		return true ;
}

int CSerialPort::Write(char* buffer, DWORD dwLen)
{
	if (IsOpen())
	{
		DWORD nNumberOfBytesToWrite = dwLen;
		DWORD dwBytesWritten=0;
		BOOL  bWriteStat = WriteFile( m_hComm,buffer,nNumberOfBytesToWrite,&dwBytesWritten, &m_OverlappedWrite);
		if( !bWriteStat)
		{
			DWORD nWriteLen ;
			int nCyc = 0 ;
 			while(GetLastError()==ERROR_IO_PENDING && nCyc < 20 && dwBytesWritten<nNumberOfBytesToWrite)
			{
				nWriteLen = 0 ;
				WaitForSingleObject( m_OverlappedWrite.hEvent, 50);
				GetOverlappedResult(m_hComm, &m_OverlappedWrite,&nWriteLen,TRUE);
				dwBytesWritten += nWriteLen ;
				nCyc++;
			}
		}
	 	return dwBytesWritten;
	}
	else
	{
		return -1 ;
	}
}
